﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Golos.Helper;
using Golos.Http;
using Golos.Polls.PollCache;
using Golos.Users.UserCache;

namespace Golos.BackEnd.Client
{
    public class PollsClient : HttpClientBase
    {
        public PollsClient(Uri serverUri) : base(serverUri)
        {
        }

        public PollsClient() : base()
        {
            serverUri = new Uri(string.Format("http://{0}/", Topology.GetEndPoint(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"settings\topology\polls"))));
        }

        public bool CreatePoll(PollInfo pollInfo)
        {
            try
            {
                var response = TrySendRequest("?operation=createpoll", "POST", pollInfo.Serialize());
                return response != null && response.StatusCode == HttpStatusCode.OK;
            }
            catch (Exception exception)
            {
                LogClass.WriteErrorEntry("Can't create poll {0}", exception.ToString());
                return false;
            }
        }

        public bool Vote(UserAnswerInfo answerInfo, AnswerProperties answerProperties)
        {
            try
            {
                var response = TrySendRequest(string.Format("?operation=vote&questionid={0}&userid={1}&answerid={2}", answerInfo.QuestionId, answerInfo.UserId, answerInfo.AnswerId), "POST", answerProperties.Serialize());
                return response != null && response.StatusCode == HttpStatusCode.OK;
            }
            catch (Exception exception)
            {
                LogClass.WriteErrorEntry("Can't create poll {0}", exception.ToString());
                return false;
            }
        }

        public UserAnswerInfo GetUserAnswerInfo(Guid questionId, Guid userId)
        {
            var response = TrySendRequest(string.Format("?operation=checkuseranswer&questionid={0}&userid={1}", questionId, userId), "GET");
            if (response.ResponseStream == null || response.StatusCode!=HttpStatusCode.OK)
                return null;
            return UserAnswerInfo.Deserialize(response.ResponseStream);
        }

        public List<Guid> GetTop10Question()
        {
            var response = TrySendRequest(string.Format("?operation=top10question"), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new List<Guid>();
            List<Guid> result = new List<Guid>();
            using (Stream stream = response.ResponseStream)
            {
                using(StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string guid = reader.ReadLine();
                        if(string.IsNullOrEmpty(guid))
                            continue;
                        result.Add(new Guid(guid));
                    }
                }
            }
            return result;
        }

        public Dictionary<Guid, int> GetVoicesCount(Guid questionId)
        {
            var response = TrySendRequest(string.Format("?operation=voicescount&questionid={0}", questionId), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new Dictionary<Guid, int>();
            Dictionary<Guid, int> result = new Dictionary<Guid, int>();
            using (Stream stream = response.ResponseStream)
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string[] str = reader.ReadLine().Split(new char[] {'\t'}, StringSplitOptions.RemoveEmptyEntries);
                        if(str.Length!=2)
                            continue;
                        result.Add(new Guid(str[0]), Convert.ToInt32(str[1]));
                    }
                }
            }
            return result;
        }

        public Dictionary<UserIdType, int> GetVoiceDistributionBySocialweb(Guid questionId)
        {
            var response = TrySendRequest(string.Format("?operation=distribution&questionid={0}&type=socialweb", questionId), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new Dictionary<UserIdType, int>();
            Dictionary<UserIdType, int> result = new Dictionary<UserIdType, int>();
            using (Stream stream = response.ResponseStream)
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string[] str = reader.ReadLine().Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
                        if (str.Length != 2)
                            continue;
                        result.Add((UserIdType)Convert.ToInt32(str[0]), Convert.ToInt32(str[1]));
                    }
                }
            }
            return result;
        }

        public PollInfo GetPollInfo(Guid questionId)
        {
            var response = TrySendRequest(string.Format("?operation=poll&questionid={0}", questionId), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return null;
            var pollInfo = PollInfo.Deserialize(response.ResponseStream);
            LogClass.WriteDebugEntry(string.Format("PollInfo ID = {0}", pollInfo.Id));
            LogClass.WriteDebugEntry(string.Format("PollInfo OwnerID = {0}", pollInfo.OwnerUserId));
            LogClass.WriteDebugEntry(string.Format("PollInfo QuestionText = '{0}'", pollInfo.QuestionText));
            LogClass.WriteDebugEntry(string.Format("PollInfo Answers count = {0}", pollInfo.Answers.Count));
            foreach (var answer in pollInfo.Answers.Keys)
            {
                LogClass.WriteDebugEntry(string.Format("PollInfo AnswerText = '{0}'", pollInfo.Answers[answer].AnswerText));
            }
            return pollInfo;
        }

        public bool MarkPollAsDeleted(Guid questionId)
        {
            try
            {
                var response = TrySendRequest(string.Format("?operation=deletequestion&questionid={0}", questionId), "DELETE");
                return response != null && response.StatusCode == HttpStatusCode.OK;
            }
            catch (Exception exception)
            {
                LogClass.WriteErrorEntry("Can't delete poll {0}", exception.ToString());
                return false;
            }
        }

        public List<Guid> GetUserQuestions(Guid userId)
        {
            var response = TrySendRequest(string.Format("?operation=myquestion&userid={0}&type=owner", userId), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new List<Guid>();
            List<Guid> result = new List<Guid>();
            using (Stream stream = response.ResponseStream)
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string guid = reader.ReadLine();
                        if (string.IsNullOrEmpty(guid))
                            continue;
                        result.Add(new Guid(guid));
                    }
                }
            }
            return result;
        }

        public List<Guid> GetVotedQuestions(Guid userId)
        {
            var response = TrySendRequest(string.Format("?operation=myquestion&userid={0}&type=voted", userId), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new List<Guid>();
            List<Guid> result = new List<Guid>();
            using (Stream stream = response.ResponseStream)
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string guid = reader.ReadLine();
                        if (string.IsNullOrEmpty(guid))
                            continue;
                        result.Add(new Guid(guid));
                    }
                }
            }
            return result;
        }

        public List<Guid> SearchPoll(string keyword)
        {
            var response = TrySendRequest(string.Format("?operation=searchpoll&keyword={0}", Convert.ToBase64String(Encoding.UTF8.GetBytes(keyword))), "GET");
            if (response.ResponseStream == null || response.StatusCode != HttpStatusCode.OK)
                return new List<Guid>();
            List<Guid> result = new List<Guid>();
            using (Stream stream = response.ResponseStream)
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    while (!reader.EndOfStream)
                    {
                        string guid = reader.ReadLine();
                        if (string.IsNullOrEmpty(guid))
                            continue;
                        result.Add(new Guid(guid));
                    }
                }
            }
            return result;
        }

        public bool MergeUserAnswer(Guid userId, List<Guid> mergeUsers)
        {
            try
            {
                byte[] data = new byte[0];
                using(MemoryStream stream = new MemoryStream())
                {
                    using(StreamWriter writer = new StreamWriter(stream))
                    {
                        foreach (Guid mergeUser in mergeUsers)
                        {
                            writer.WriteLine(mergeUser.ToString());
                        }
                        writer.Flush();
                    }
                    data = stream.ToArray();
                }
                var response = TrySendRequest(string.Format("?operation=mergeanswers&userid={0}", userId), "POST", data);
                return response != null && response.StatusCode == HttpStatusCode.OK;
            }
            catch (Exception exception)
            {
                LogClass.WriteErrorEntry("Can't create poll {0}", exception.ToString());
                return false;
            }
        }
    }
}
